/*
 * Copyright 2008 Carnegie Mellon University
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package edu.cmu.lti.sepia.infra.topic;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;

import edu.cmu.lti.sepia.infra.topic.model.Answer;
import edu.cmu.lti.sepia.infra.topic.model.Nugget;
import edu.cmu.lti.sepia.infra.topic.model.Topic;
import edu.cmu.lti.sepia.util.FormatUtil;

public class GoldStandardObjToXml {

  public static String toQuestionXml( List<Topic> topics, String srcLang, String trgLang, String taskDescription ) {
    return toXml(topics,srcLang,trgLang,taskDescription,true);
  }
  
  public static String toGoldStandardXml( List<Topic> topics, String srcLang, String trgLang, String taskDescription ) {
    return toXml(topics,srcLang,trgLang,taskDescription,false);
  }
  
  private static String toXml( List<Topic> topics, String srcLang, String trgLang, String taskDescription, boolean questionsOnly ) {
    String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime());
    
    boolean isMonolingual = srcLang.equals(trgLang);
    
    //TODO: read DTD from file
    StringBuilder sb = new StringBuilder();
    sb.append( getDTD() );

    sb.append("<TOPIC_SET>\n");
    sb.append("  <METADATA>\n");
    sb.append("    <DESCRIPTION>"+taskDescription+"</DESCRIPTION>\n");
    sb.append("    <VERSION>"+date+"</VERSION>\n");
    sb.append("    <LANGUAGE TARGET=\""+trgLang+"\"/>\n");
    sb.append("    <CORPUS></CORPUS>\n");
    sb.append("  </METADATA>\n");

    for (int i=0;i<topics.size();i++){
      Topic t = topics.get(i);
      List<Answer> answers = t.getAnswers();
      List<Nugget> nuggets = t.getNuggets();

      sb.append("  <TOPIC ID=\""+t.getExternalId()+"\"" );
      if (!questionsOnly) {
        sb.append(" TITLE=\""+unescape(t.getTitle())+"\"");
      }
      sb.append(">\n");
      if (!isMonolingual) {
        sb.append("    <QUESTION LANG=\""+srcLang+"\"><![CDATA["+unescape(t.getQuestionSrc())+"]]></QUESTION>\n");
      }
      sb.append("    <QUESTION LANG=\""+trgLang+"\"><![CDATA["+unescape(t.getQuestionTrg())+"]]></QUESTION>\n");
      if (!questionsOnly) { 
        sb.append("    <ANSWERTYPE>"+t.getAnswerType()+"</ANSWERTYPE>\n" ); 
      }
      if (!isMonolingual) {
        sb.append("    <NARRATIVE LANG=\""+srcLang+"\"><![CDATA["+unescape(t.getNarrativeSrc())+"]]></NARRATIVE>\n");
      }
      sb.append("    <NARRATIVE LANG=\""+trgLang+"\"><![CDATA["+unescape(t.getNarrativeTrg())+"]]></NARRATIVE>\n");
      if (!questionsOnly) {
        if (answers==null && nuggets==null) {
          sb.append("    <ANSWER />\n");
        } else {
          sb.append("    <ANSWER>\n");
          if (answers!=null) {
            for ( int j=0; j<answers.size(); j++ ) {
              Answer a = answers.get(j);
              sb.append("      <TEXT ID=\""+(j+1)+"\" DOCNO=\""+a.getDocumentId()+"\"");
              sb.append(a.getLabel().length()>0?" LABEL=\""+a.getLabel()+"\"":"");
              sb.append(a.getBegin()>0&&a.getEnd()>0?(" BEGIN=\""+a.getBegin()+"\" END=\""+a.getEnd()+"\" ORIGINAL=\""+a.getOriginalAnswerBearingText().replaceAll("\"", "\\\\\"")+"\""):"");
              sb.append("><![CDATA["+a.getAnswerBearingText()+"]]></TEXT>\n");
            }
          }
      
          if (nuggets!=null) {
            for ( int j=0; j<nuggets.size(); j++ ) {
              Nugget n = nuggets.get(j);
              sb.append("      <NUGGET ID=\""+(j+1)+"\" VITAL=\""+n.getVitalCount()+"\" NONVITAL=\""+n.getNonVitalCount()+"\" SCORE=\""+FormatUtil.nf4(n.getWeight())+"\"><![CDATA["+n.getText()+"]]></NUGGET>\n");  
            }//end of NUGGET
          }
          sb.append("    </ANSWER>\n");  
        }
      }//end of if question only

      sb.append("  </TOPIC>\n");
    }
    sb.append("</TOPIC_SET>\n");
    return sb.toString();
  }

  private static String getDTD() {
    StringBuilder sb = new StringBuilder();
    sb.append("<!DOCTYPE TOPIC_SET [\n");
    sb.append("<!ELEMENT TOPIC_SET (METADATA,TOPIC+)>\n");
    sb.append("<!ELEMENT METADATA (DESCRIPTION, VERSION, LANGUAGE, CORPUS)>\n");
    sb.append("<!ELEMENT DESCRIPTION (#PCDATA)>\n");
    sb.append("<!ELEMENT VERSION  (#PCDATA)>\n");
    sb.append("<!ELEMENT LANGUAGE (#PCDATA)>\n");
    sb.append("<!ATTLIST LANGUAGE SOURCE (EN|JA|CT|CS) #IMPLIED>\n");
    sb.append("<!ATTLIST LANGUAGE TARGET (EN|JA|CT|CS) #REQUIRED>\n");
    sb.append("<!ELEMENT CORPUS (#PCDATA)>\n");
    sb.append("<!ELEMENT TOPIC (QUESTION+,ANSWERTYPE*,NARRATIVE+,ANSWER*)>\n");
    sb.append("<!ATTLIST TOPIC ID    CDATA #REQUIRED>\n");
    sb.append("<!ATTLIST TOPIC TITLE CDATA #IMPLIED>\n");
    sb.append("<!ELEMENT QUESTION (#PCDATA)>\n");
    sb.append("<!ATTLIST QUESTION LANG (EN|JA|CT|CS) #REQUIRED>\n");
    sb.append("<!ELEMENT ANSWERTYPE (#PCDATA)>\n");
    sb.append("<!ELEMENT NARRATIVE (#PCDATA)>\n");
    sb.append("<!ATTLIST NARRATIVE LANG (EN|JA|CT|CS) #REQUIRED>\n");
    sb.append("<!ELEMENT ANSWER (TEXT*,NUGGET*)>\n");    
    sb.append("<!ELEMENT TEXT           (#PCDATA)>\n");
    sb.append("<!ATTLIST TEXT ID         CDATA #REQUIRED>\n");
    sb.append("<!ATTLIST TEXT DOCNO      CDATA #REQUIRED>\n");
    sb.append("<!ATTLIST TEXT LABEL      CDATA #IMPLIED>\n");
    sb.append("<!ATTLIST TEXT BEGIN      CDATA #IMPLIED>\n");
    sb.append("<!ATTLIST TEXT END        CDATA #IMPLIED>\n");
    sb.append("<!ATTLIST TEXT ORIGINAL   CDATA #IMPLIED>\n");
    sb.append("<!ELEMENT NUGGET          (#PCDATA)>\n");
    sb.append("<!ATTLIST NUGGET ID       CDATA #REQUIRED>\n");
    sb.append("<!ATTLIST NUGGET VITAL    CDATA #REQUIRED>\n");
    sb.append("<!ATTLIST NUGGET NONVITAL CDATA #REQUIRED>\n");
    sb.append("<!ATTLIST NUGGET SCORE    CDATA #REQUIRED>\n");
    sb.append("]>\n");
    return sb.toString();
  }
  
  private static String unescape(String text){
    return text.replaceAll("&apos;","'");
  }
  
}
